<template>
	<view class="chat">
		<scroll-view
			:style="{height: `${windowHeight - inputHeight}rpx`}"
			id="scrollview"
			scroll-y="true"
			:scroll-top="scrollTop"
			class="scroll-view"
			@scrolltoupper="scrolltoupper"
			@scroll="scroll"
			:scroll-into-view="tabNumId"
		>
			<!-- 聊天主体 -->
			<view id="msglistview" class="chat-body" v-if="msgList.rows?.length > 0">
				<view class="loading_box" :style="{opacity: topLoading ? 1 : 0}">
					<view class="loading_title">
						<view class="c1 box"></view>
						<view class="c2 box"></view>
						<view class="c3 box"></view>
						<view class="c4 box"></view>
						<view class="c5 box"></view>
						<view class="c6 box"></view>
						<view class="c7 box"></view>
						<view class="c8 box"></view>
					</view>
				</view>
				<!-- 聊天记录 -->
				<view
					v-for="(item, index) in msgList.rows"
					:key="index"
					:id="'tabNum' + (msgList.rows.length - index)"
				>
					<!-- 自己发的消息 -->
					<view
						class="item_box"
						v-if="item.empId === store.state.userInfo.empAccountId"
					>
						<view
							class="item_time"
							v-if="
								index > 0
									? new Date(
											item.createTime.replace(/-/g, '/') + ':00',
									  ).getTime() >=
									  new Date(
											msgList.rows[index - 1].createTime.replace(/-/g, '/') +
												':00',
									  ).getTime() +
											300000
									: true
							"
						>
							<span class="tip">{{ formatChatTime(item.createTime) }}</span>
						</view>
						<view class="item self">
							<view class="name">
								{{
									`${item.emp}(${
										item.empType == 1
											? '客服'
											: item.empType == 2
											? '服务商'
											: item.empType == 3
											? '工程师'
											: '工单客服'
									})`
								}}
							</view>
							<view class="item_content">
								<!-- 文字内容 -->
								<view class="img_list">
									<view v-if="item.content.length > 0" class="content right">
										{{ item.content }}
									</view>
									<image
										v-if="item.annexs.length > 0"
										v-for="(img, index) in item.annexs"
										:key="index"
										@click="lookImg(img)"
										:lazy-load="true"
										mode="aspectFill"
										class="content_img"
										:src="img"
									/>
								</view>

								<!-- 头像 -->
								<view class="avatar">
									<image
										mode="aspectFit"
										:lazy-load="true"
										class="user_img"
										v-if="item.avatar"
										:src="item.avatar"
									/>
									<uni-icons
										size="40"
										color="#007cff"
										type="person-filled"
										v-else
									></uni-icons>
								</view>
							</view>
						</view>
					</view>
					<!-- 对方发的消息 -->
					<view class="item_box" v-else>
						<view
							class="item_time"
							v-if="
								index > 0
									? new Date(
											item.createTime.replace(/-/g, '/') + ':00',
									  ).getTime() >=
									  new Date(
											msgList.rows[index - 1].createTime.replace(/-/g, '/') +
												':00',
									  ).getTime() +
											300000
									: true
							"
						>
							<span class="tip">{{ formatChatTime(item.createTime) }}</span>
						</view>
						<view class="item">
							<view class="name">
								{{
									`${item.emp}(${
										item.empType == 1
											? '客服'
											: item.empType == 2
											? '服务商'
											: item.empType == 3
											? '工程师'
											: '工单客服'
									})`
								}}
							</view>
							<view class="item_content">
								<!-- 头像 -->
								<view class="avatar">
									<image
										mode="aspectFit"
										:lazy-load="true"
										class="user_img"
										v-if="item.avatar"
										:src="item.avatar"
									/>
									<uni-icons
										size="40"
										color="#007cff"
										type="person-filled"
										v-else
									></uni-icons>
								</view>

								<!-- 文字内容 -->
								<view class="img_list">
									<view v-if="item.content.length > 0" class="content left">
										{{ item.content }}
									</view>
									<image
										v-if="item.annexs.length > 0"
										v-for="(img, index) in item.annexs"
										:key="index"
										@click="lookImg(img)"
										:lazy-load="true"
										mode="aspectFill"
										class="content_img"
										:src="img"
									/>
								</view>
							</view>
						</view>
					</view>
				</view>
				<view class="loading_box" v-if="Loading">
					<view class="loading_title">
						<view class="c1 box"></view>
						<view class="c2 box"></view>
						<view class="c3 box"></view>
						<view class="c4 box"></view>
						<view class="c5 box"></view>
						<view class="c6 box"></view>
						<view class="c7 box"></view>
						<view class="c8 box"></view>
					</view>
				</view>
			</view>
		</scroll-view>
		<!-- 底部消息发送栏 -->
		<!-- 用来占位，防止聊天消息被发送框遮挡 -->
		<view
			class="chat-bottom"
			ref="sendBoxRef"
			:style="{height: `${inputHeight}rpx`}"
		>
			<view class="send-box" :style="{bottom: `${keyboardHeight}rpx`}">
				<uni-data-checkbox
					v-model="leaveMessageVo.visitTypes"
					multiple
					:localdata="visibleList"
				/>
				<view class="send-msg">
					<view class="uni-textarea">
						<textarea
							@keyboardheightchange="onKeyboardHeightChange"
							v-model="chatMsg"
							maxlength="500"
							confirm-type="send"
							:show-confirm-bar="false"
							:adjust-position="false"
							@linechange="sendHeight"
							@focus="focus"
							@blur="blur"
							auto-height
						></textarea>
					</view>
					<view @click="handleSend" class="send-btn" v-if="chatMsg">发送</view>
					<view class="example_pic" v-else>
						<!-- #ifdef APP-PLUS -->
						<uni-icons
							color="#007cff"
							type="image"
							size="34"
							@click="onUpdateImgClick"
						></uni-icons>
						<!-- #endif -->

						<!-- #ifdef H5 || MP-WEIXIN -->
						<uni-file-picker
							limit="9"
							:sizeType="['original', 'compressed']"
							:sourceType="['album', 'camera']"
							file-mediatype="image"
							:imageStyles="imageStyles"
							file-extname="png,jpg"
							@select="select"
						>
							<uni-icons color="#007cff" type="image" size="34"></uni-icons>
						</uni-file-picker>
						<!-- #endif -->
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script lang="ts" setup>
	import {
		ref,
		onMounted,
		reactive,
		watch,
		nextTick,
		onUpdated,
		computed,
		getCurrentInstance,
	} from 'vue';
	import {
		onReachBottom,
		onPullDownRefresh,
		onUnload,
		onShow,
		onLoad,
		onHide,
	} from '@dcloudio/uni-app';
	import apiMessage from '@/util/network_api/apiMessage.js';
	import store from '@/store_network/index.js';
	import apiUpload from '@/util/network_api/upload.js';
	import _ from 'lodash';
	import { useReadFileByPath } from '@/hooks/useAppPlus'
	
	const keyboardHeight = ref(0); //键盘高度
	const bottomHeight = ref(0); // 聊天框距离底部的高度
	const scrollTop = ref(0); //滚动距离
	const oldScrollTop = ref(0);
	const sendBoxRef = ref();
	const leaveMessageVo = ref({
		annex: [],
		content: '',
		visitTypes: [0], //可见类型：0-公开，1-服务商，2-工程师，3-工单客户
		workId: '',
	});
	const chatMsg = ref(''); //发送的消息
	const msgList = ref({total: 0, rows: []});
	const focusInput = ref(false);
	const workId = ref(''); //工单Id
	const visibleList = ref([
		{text: '所有人可见', value: 0},
		{text: '仅总部可见', value: 4},
	]);
	const imageStyles = {
		width: 60,
		height: 40,
	};
	const Loading = ref(false); //发送信息loading
	const topLoading = ref(false); //顶部loading
	const tabNumId = ref();
	onLoad((e) => {
		leaveMessageVo.value.workId = e.WorkId;
		workId.value = e.workId;
	});
	const instance = getCurrentInstance(); // 获取组件实例
	// 监听键盘弹起来的高度
	const onKeyboardHeightChange = (res) => {
		keyboardHeight.value = rpxTopx(res.detail.height);
		if (keyboardHeight.value < 0) keyboardHeight.value = 0;
	};
	const windowHeight = computed(() => {
		return rpxTopx(uni.getSystemInfoSync().windowHeight);
	});
	// 键盘弹起来的高度+发送框高度
	const inputHeight = computed(() => {
		return bottomHeight.value + keyboardHeight.value;
	});
	const focus = () => {
		scrollToBottom();
	};
	const blur = () => {
		scrollToBottom();
	};
	// px转换成rpx
	function rpxTopx(px) {
		let deviceWidth = wx.getSystemInfoSync().windowWidth;
		let rpx = (750 / deviceWidth) * Number(px);
		return Math.floor(rpx);
	}
	// 监视聊天发送栏高度
	function sendHeight() {
		setTimeout(() => {
			let query = uni.createSelectorQuery().in(instance.refs.sendBoxRef);
			query.select('.send-box').boundingClientRect();
			query.exec((res) => {
				bottomHeight.value = rpxTopx(res[0].height);
			});
		}, 30);
	}
	// 滚动至聊天底部
	function scrollToBottom() {
		setTimeout(() => {
			let query = uni.createSelectorQuery().in(instance);
			query.select('#scrollview').boundingClientRect();
			query.select('#msglistview').boundingClientRect();
			query.exec((res) => {
				if (res[1]?.height > res[0]?.height) {
					scrollTop.value = rpxTopx(res[1].height - res[0].height);
				}
			});
		}, 80);
	}
	// 发送消息
	async function handleSend() {
		//如果消息不为空
		if (chatMsg.value.trim() != '' || leaveMessageVo.value.annex.length > 0) {
			leaveMessageVo.value.content = chatMsg.value.trim();
			leaveMessageVo.value.workId = workId.value;
			Loading.value = true;
			await apiMessage
				.saveNetworkOrderMessage(leaveMessageVo.value)
				.then(async (res) => {
					if (res.code == 20000) {
						getNetworkOrderMessageList();
					}
				});
			chatMsg.value = '';
			leaveMessageVo.value.annex = [];
			focusInput.value = true;
		} else {
			uni.showToast({title: '不能发送空白消息', icon: 'none'});
		}
	}
	// 判断日期并返回不同格式的时间
	function formatChatTime(time) {
		const datetime: any = new Date(time.replace(/-/g, '/') + ':00');
		const now: any = new Date();
		const yesterday = new Date(now);
		yesterday.setDate(now.getDate() - 1);
		const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
		const hour = datetime.getHours();
		let str = '';
		if (hour >= 0 && hour < 12) {
			str = '上午';
		} else if (hour >= 12 && hour < 18) {
			str = '下午';
		} else {
			str = '晚上';
		}
		if (datetime.toDateString() === now.toDateString()) {
			return (
				str +
				' ' +
				datetime.getHours().toString().padStart(2, '0') +
				':' +
				datetime.getMinutes().toString().padStart(2, '0')
			);
		} else if (yesterday.toDateString() === datetime.toDateString()) {
			return (
				'昨天 ' +
				str +
				' ' +
				datetime.getHours().toString().padStart(2, '0') +
				':' +
				datetime.getMinutes().toString().padStart(2, '0')
			);
		} else if (Math.floor((now - datetime) / (1000 * 60 * 60 * 24 * 7)) === 0) {
			return (
				days[datetime.getDay()] +
				' ' +
				str +
				datetime.getHours().toString().padStart(2, '0') +
				':' +
				datetime.getMinutes().toString().padStart(2, '0')
			);
		} else if (datetime.getFullYear() == now.getFullYear()) {
			return (
				datetime.getMonth() +
				1 +
				'月' +
				datetime.getDate() +
				'日 ' +
				datetime.getHours().toString().padStart(2, '0') +
				':' +
				datetime.getMinutes().toString().padStart(2, '0')
			);
		} else {
			return time;
		}
	}
	// 滚动到顶部
	const scrolltoupper = () => {
		if (msgList.value.total > msgList.value.rows.length && !topLoading.value) {
			pageUtil.value.page += 1;
			topLoading.value = true;
			getNetworkOrderMessageList();
		}
	};
	// 预览图片
	const lookImg = (url: any) => {
		uni.previewImage({
			urls: [url],
			indicator: 'none',
		});
	};
	const pageUtil = ref({
		limit: 0,
		page: 1,
	});
	// 获取聊天列表
	const getNetworkOrderMessageList = async () => {
		await apiMessage
			.getNetworkOrderMessage(pageUtil.value, workId.value)
			.then((res) => {
				if (res.code == 20000) {
					if (
						msgList.value.total > msgList.value.rows.length &&
						pageUtil.value.page > 1
					) {
						// msgList.value.rows = [...res.data.rows, ...msgList.value.rows]
						msgList.value.rows.unshift(...res.data.rows);
						nextTick(() => {
							// 滚动到顶部 原来位置
							tabNumId.value =
								'tabNum' + (msgList.value.rows.length - res.data.rows.length);
						});
					} else {
						msgList.value.rows = res.data.rows;
					}
					msgList.value.total = res.data.total - 0;
					if (topLoading.value) {
						topLoading.value = false;
					} else {
						scrollToBottom();
					}
				}
			});
		Loading.value = false;

		// uni.hideLoading()
	};
	const scroll = (e) => {
		oldScrollTop.value = e.detail.scrollHeight;
	};
	onShow(() => {
		msgList.value.rows = [];
		msgList.value.total = 0;
		pageUtil.value.page = 1;
		if (!workId.value) return;
		getNetworkOrderMessageList();
	});
	// 图片选择发送
	const select = (img) => {
		uni
			.showModal({
				title: '提示',
				content: '确认上传图片？',
			})
			.then(async (res) => {
				//确认
				if (res.confirm) {
					new Promise(async () => {
						let arrImg = [];
						for (let i = 0; i < img.tempFiles.length; i++) {
							await apiUpload
								.uploadOrderFile({files: img.tempFiles[i].file})
								.then((res) => {
									arrImg.push(res.data.rows[0]);
								});
						}
						leaveMessageVo.value.annex = arrImg;
						handleSend();
					});
				}
			});
	};

	/**
	 * 上传图片点击事件，只有在APP端时才调用这个方法，因为要提示用户获取权限才能以通过应用市场的上架
	 */
	const onUpdateImgClick = () => {
		uni.showModal({
			title: '提示',
			content: '确认上传图片？',
			success: (res) => {
				if (res.confirm) {
					const Manifest = plus.android.importClass('android.Manifest');
					const MainActivity = plus.android.runtimeMainActivity();
					if (
						MainActivity.checkSelfPermission(Manifest.permission.CAMERA) === -1
					) {
						uni.showModal({
							title: '请允许我们使用相机权限',
							content:
								'允许“叮咚到家平台”在您使用该应用时访问您的相机吗？允许访问才能拍摄图片用于发送消息',
							mask: true,
							icon: 'none',
							showCancel: true,
							cancelText: '我知道了',
							confirmText: '前往设置',
							success: (res) => {
								if (res.confirm) {
									uni.openAppAuthorizeSetting();
								}
							},
						});
						return;
					}

					if (
						MainActivity.checkSelfPermission(
							Manifest.permission.READ_EXTERNAL_STORAGE,
						) === -1
					) {
						uni.showModal({
							title: '请允许我们获取相册权限',
							content:
								'允许“叮咚到家平台”在您使用该应用时访问您的相册吗？允许访问才能获取您相册的图片用于发送消息',
							mask: true,
							icon: 'none',
							showCancel: true,
							cancelText: '我知道了',
							confirmText: '前往设置',
							success: (res) => {
								if (res.confirm) {
									uni.openAppAuthorizeSetting();
								}
							},
						});
						return;
					}

					uni.showActionSheet({
						itemList: ['拍摄', '从相册选择'],
						success: (res: {tapIndex: number}) => {
							if (res.tapIndex === 0) {
								uni.chooseImage({
									sourceType: ['camera'],
									success: async (res: {
										tempFiles: Array<File>;
										tempFilePaths: Array<string>;
									}) => {
										const files = [];
										for (let i = 0; i < res.tempFiles.length; i++) {
											const file = await useReadFileByPath(res.tempFiles[i].path)
											files.push(file);
										}
										
										const arrImg = [];
										for (let i = 0; i < files.length; i++) {
											const res = await apiUpload.uploadOrderFile({
												files: files[i],
											});
											arrImg.push(res.data.rows[0]);
										}
										leaveMessageVo.value.annex = arrImg;
										handleSend();
									},
								});
							} else {
								uni.chooseImage({
									sourceType: ['album'],
									success: async (res: {
										tempFiles: Array<File>;
										tempFilePaths: Array<string>;
									}) => {
										const files = [];
										for (let i = 0; i < res.tempFiles.length; i++) {
											const file = await useReadFileByPath(res.tempFiles[i].path)
											files.push(file);
										}

										const arrImg = [];
										for (let i = 0; i < files.length; i++) {
											const res = await apiUpload.uploadOrderFile({
												files: files[i],
											});
											arrImg.push(res.data.rows[0]);
										}
										leaveMessageVo.value.annex = arrImg;
										handleSend();
									},
								});
							}
						},
					});
				}
			},
		});
	};
</script>

<style lang="scss" scoped>
	$chatContentbgc: #c2dcff;
	$sendBtnbgc: #4f7df5;

	view,
	button,
	text,
	input,
	textarea {
		margin: 0;
		padding: 0;
		box-sizing: border-box;
	}

	/* 聊天消息 */
	.chat {
		.scroll-view {
			::-webkit-scrollbar {
				display: none;
				width: 0 !important;
				height: 0 !important;
				-webkit-appearance: none;
				background: transparent;
				color: transparent;
			}

			background-color: #fafafa;

			.chat-body {
				display: flex;
				flex-direction: column;
				padding-top: 4rpx;

				.item_box {
					display: flex;
					flex-direction: column;
					padding: 0 30rpx 30rpx;

					.item_time {
						display: flex;
						justify-content: center;
						color: #999;
						font-size: 24rpx;

						.tip {
							background-color: rgb(218, 218, 218);
							padding: 4rpx 8rpx;
							border-radius: 6rpx;
							color: #fff;
						}
					}

					.self {
						align-items: flex-end;
					}

					.item {
						display: flex;
						flex-direction: column;

						.right {
							background-color: $chatContentbgc;
						}

						.left {
							background-color: #ffffff;
						}

						&_content {
							display: flex;
						}

						.name {
							font-size: 24rpx;
							overflow: hidden;
							text-overflow: ellipsis;
							white-space: nowrap;
							padding-bottom: 8rpx;
							color: #555;
						}

						// 聊天消息的三角形
						.right::after {
							position: absolute;
							display: inline-block;
							content: '';
							width: 0;
							height: 0;
							left: 100%;
							top: 10px;
							border: 12rpx solid transparent;
							border-left: 12rpx solid $chatContentbgc;
						}

						.left::after {
							position: absolute;
							display: inline-block;
							content: '';
							width: 0;
							height: 0;
							top: 10px;
							right: 100%;
							border: 12rpx solid transparent;
							border-right: 12rpx solid #ffffff;
						}

						.content {
							position: relative;
							max-width: 486rpx;
							border-radius: 8rpx;
							word-wrap: break-word;
							padding: 20rpx;
							margin: 0 24rpx;
							border-radius: 5px;
							font-size: 28rpx;
							color: #333333;
							line-height: 40rpx;
						}

						.img_list {
							display: flex;
							flex-direction: column;
						}

						.content_img {
							max-width: 320rpx;
							max-height: 320rpx;
							margin: 10rpx 24rpx;
							border: 1rpx solid #fafafa;
						}

						.avatar {
							display: flex;
							justify-content: center;
							width: 78rpx;
							height: 78rpx;
							border-radius: 8rpx;
							overflow: hidden;
							background-color: $chatContentbgc;

							.user_img {
								align-self: center;
								width: 78rpx;
								height: 78rpx;
							}
						}
					}
				}
			}
		}

		.loading_box {
			display: flex;
			align-items: center;
			justify-content: center;
		}

		.loading_title {
			width: 60rpx;
			height: 60rpx;
			position: relative;

			.box {
				position: absolute;
				height: 10rpx;
				width: 10rpx;
				left: 50%;
				transform: translateX(-50%);
				background-color: #999;
				border-radius: 50%;
				transform-origin: center 20rpx;
				animation-name: loading_title;
				animation-timing-function: linear;
				animation-duration: 0.8s;
				animation-iteration-count: infinite;
				animation-direction: inherit;
			}

			.c1 {
				animation-delay: -0.8s;
			}

			.c2 {
				animation-delay: -0.7s;
			}

			.c3 {
				animation-delay: -0.6s;
			}

			.c4 {
				animation-delay: -0.5s;
			}

			.c5 {
				animation-delay: -0.4s;
			}

			.c6 {
				animation-delay: -0.3s;
			}

			.c7 {
				animation-delay: -0.2s;
			}

			.c8 {
				animation-delay: -0.1s;
			}
		}

		@keyframes loading_title {
			from {
				transform: rotate(0deg) scale(1);
				opacity: 1;
			}

			to {
				transform: rotate(360deg) scale(1);
				opacity: 0.2;
			}
		}

		/* 底部聊天发送栏 */
		.chat-bottom {
			width: 100%;
			background: #f4f5f7;
			transition: all 0.1s ease;
			position: fixed;
			bottom: 0;

			.send-box {
				background: #ededed;
				padding: 20rpx 30rpx 30rpx;
				width: 100%;
				position: fixed;
				bottom: 0;
				transition: all 0.1s ease;

				.send-msg {
					display: flex;
					align-items: flex-end;
					justify-content: space-between;
					background: #ededed;
					margin-top: 20rpx;
					flex: 1;
				}

				:deep(.checklist-group) {
					width: 100%;
					display: flex;
					align-items: center;
					justify-content: space-around;
				}
			}

			.uni-textarea {
				flex: 1;
				background-color: #ffffff;
				padding: 12rpx;
				border-radius: 8rpx;

				textarea {
					width: 100%;
					min-height: 70rpx;
					max-height: 200rpx !important;
					background: #ffffff;
					transition: all 0.3s ease-in-out;
					font-size: 30rpx;
					color: #333333;
					overflow-y: auto;
					flex: 1;
				}
			}

			.example_pic {
				margin-left: 30rpx;
				width: 60rpx;
				height: 50rpx;
				display: flex;
				align-items: center;
				justify-content: flex-end;
				margin-bottom: 20rpx;
			}

			:deep(.file-picker__box) {
				display: none;

				&:last-child {
					display: block;
					border: 1px solid red;
					box-sizing: border-box;
				}
			}

			.send-btn {
				display: flex;
				align-items: center;
				justify-content: center;
				margin-left: 30rpx;
				border-radius: 20rpx;
				font-size: 28rpx;
				font-weight: 500;
				color: #00c0c0;
				width: 60rpx;
				height: 50rpx;
				margin-bottom: 20rpx;
			}
		}
	}
</style>
